package com.itcoon.cloud.framework.utils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class MapUtils {

    public  static <T,R> Map<R,T> map(Collection<T> cols, Function<T, R> sf){
        Map<R, T> map = new HashMap<>();
        cols.forEach(c->map.put(sf.apply(c),c));
        return map;
    }

    @Deprecated
    public static <T,R> List<R> mapAs(List<T> cols, Function<T, R> sf){
       return cols.stream().map(sf).collect(Collectors.toList());
    }

    public static <T,R> List<R> mapAsList(Collection<T> cols, Function<T, R> sf){
        return cols.stream().map(sf).collect(Collectors.toList());
    }

    public static <T,R> Set<R> mapAsSet(Collection<T> cols, Function<T, R> sf){
        return cols.stream().map(sf).collect(Collectors.toSet());
    }

    public static <T,R> Map<R,List<T>> mapList(Collection<T> cols, Function<T, R> sf){
        return cols.stream().collect(Collectors.groupingBy(sf));
    }

    public static <T> T fromMap(Map<String, ?> map, Class<T> targetClass) {
        try {
            T t = targetClass.newInstance();
            BeanInfo beanInfo = Introspector.getBeanInfo(targetClass);
            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : descriptors) {
                Object fieldVal =  map.get(descriptor.getName());
                Method method = descriptor.getWriteMethod();
                if(fieldVal != null){
                    method.invoke(t, fieldVal);
                }
            }
            return t;
        }catch (Exception ignored){
            return null;
        }
    }

    public static <T> Map<String, ?> toMap(T t) {
        Class<T> clazz = (Class<T>) t.getClass();
        Map<String, Object> resultMap = new HashMap<>();
       try {
           BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
           PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
           for (PropertyDescriptor descriptor : descriptors) {
               Method method = descriptor.getReadMethod();
               if(!method.getDeclaringClass().equals(Object.class)){
                   Object value = method.invoke(t);
                   if(value != null){
                       resultMap.put(descriptor.getName(), method.invoke(t));
                   }
               }
           }
       }catch (Exception ignored){
       }
       return resultMap;
    }
}
